package com.leps.nq.tx.core;

import com.leps.nq.common.util.DataUtils;
import lombok.Getter;
import lombok.Setter;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

@Getter
@Setter
public class WriteRequest extends AbstractRequest {
    private int firstAddress;
    private String dataTypeStr;
    private int dataAddress;
    private int dataValue;

    final static byte[] DEFAULT_HEAD  = DataUtils.hexStrToBytes("55 06 55");
    final static byte[] DEFAULT_TAIL = DataUtils.hexStrToBytes("00");
    final static Map<String, Byte> DATA_TYPE_MAPPING = new HashMap<>();
    static {
        DATA_TYPE_MAPPING.put("VB", (byte)1);
        DATA_TYPE_MAPPING.put("VW", (byte)2);
        DATA_TYPE_MAPPING.put("VD", (byte)3);
        // ignore case
        DATA_TYPE_MAPPING.put("vb", (byte)1);
        DATA_TYPE_MAPPING.put("vw", (byte)2);
        DATA_TYPE_MAPPING.put("vd", (byte)3);
    }

    public int dataAddressMinusFirstAddress() {
        return this.dataAddress - this.firstAddress;
    }

    public WriteRequest(String ip, int port, String plcPwdStr, int firstAddress) {
        super(ip, port, plcPwdStr);
        this.head = DEFAULT_HEAD;
        this.tail = DEFAULT_TAIL;
        this.firstAddress = firstAddress;
    }

    public WriteRequest(String ip, int port, String plcPwdStr, int firstAddress, String dataTypeStr, int dataAddress, int dataValue) {
        this(ip, port, plcPwdStr, firstAddress);
        this.plcPwdStr = plcPwdStr;
        this.dataTypeStr = dataTypeStr;
        this.dataAddress = dataAddress;
        this.dataValue = dataValue;
    }

    public byte[] getDatagram() {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        try {
            byteArrayOutputStream.write(this.head);
            byteArrayOutputStream.write(this.plcPwdStr.getBytes());
            byteArrayOutputStream.write(DATA_TYPE_MAPPING.get(this.dataTypeStr));
            byteArrayOutputStream.write(DataUtils.intToWord(this.dataAddressMinusFirstAddress()));
            byteArrayOutputStream.write(DataUtils.intToDword(dataValue));
            byteArrayOutputStream.write(this.tail);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return byteArrayOutputStream.toByteArray();
    }

    public String getDatagramHexStr() {
        return DataUtils.bytesToHexStr(this.getDatagram());
    }

}
